package com.jeesuite.monitor.component.method;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jeesuite.monitor.common.asm.MethodInjectHandler;
import com.jeesuite.monitor.constant.MonitorContants;
import com.jeesuite.monitor.core.MonitorContext;
import com.jeesuite.monitor.core.TraceManager;
import com.jeesuite.monitor.model.metaobject.MethodTrace;
import com.jeesuite.monitor.model.metaobject.Trace.TraceType;

/**
 * 监听方法调用的handle，在MethodComponent中对配置的包以及类的方法调用进行监听
 * @description <br>
 * @author <a href="mailto:vakinge@gmail.com">vakin</a>
 * @date 2016年6月15日
 */
public class TraceMethodHandle implements MethodInjectHandler {
	
	private static Logger log = LoggerFactory.getLogger(TraceMethodHandle.class);
	
	/**
	 * 运行轨迹容器
	 */
	private  transient TraceManager _container=null;
	
	public TraceMethodHandle(TraceManager container) {
		_container=container;
	}

	private TraceManager getContainer(){
		return _container;
	}
	
	public Object invoke(Object target, Method method, Method methodProxy, Object[] args)throws Throwable{
		Object o;
		MethodTrace trace = null;
		String mod = Modifier.toString(method.getModifiers());
		boolean doTrace = mod.indexOf("public")>=0 && mod.indexOf("static")<0;
		try {
			try {
				if(doTrace){
					boolean traceStack = Boolean.parseBoolean(MonitorContext.getComponentProps(TraceType.METHOD.name(), MonitorContants.CONF_TRACE_STACK));
					trace = new MethodTrace(target, method, args,traceStack);
					getContainer().activateTrace(TraceType.METHOD.name(),trace);
				}
				
			} catch (Exception e) {
				doTrace = false;
				//log.warn(e.getMessage());
			}
			
			o = methodProxy.invoke(target, args);
			if(doTrace)trace.setSuccessed(true);
		}catch(InvocationTargetException e){
			if(doTrace){
				trace.setSuccessed(false);
				trace.setStack(e);
			}
			//抛出原有异常
			throw e.getCause(); 
		}finally {
			if(doTrace){
				try {
					getContainer().inactivateTrace(TraceType.METHOD.name(),trace);
				} catch (Exception e) {
					log.warn("["+method.getName() + "]监控代码未正常结束");
				}
			}
		}

		return o;

	}

}

